#!/usr/bin/perl

#===============================================================================
#     REVISION:  $Id$
#  DESCRIPTION:  Test for Meter::Meterings
#===============================================================================

use strict;
use warnings;

use Readonly;
Readonly our $VERSION => qw($Revision$) [1];

use English qw( -no_match_vars );

#use Smart::Comments;
#$ENV{'DONT_CLEANUP'} = 1;

use Meter::Test qw(
    init_tmp_db
);

use Meter::Users;
use Meter::Houses;
use Meter::Appartments;
use Meter::Meterings;

use Meter::Utils qw(
    dump_compact
);

use Test::More tests => 6 + 1 + 1;
use Test::Exception;
use Test::DatabaseRow;

Readonly my $USERNAME => 'user1';
Readonly my $EMAIL    => 'email1@example.com';
Readonly my $PASSWORD => '123456';

Readonly my $ADDRESS => 'Коломяжский пр-т 15-1';

Readonly my $APPARTMENT_NUMBER       => 123;
Readonly my $FIRST_NAME              => 'Александр';
Readonly my $LAST_NAME               => 'Симаков';
Readonly my $MIDDLE_NAME             => 'Владимирович';
Readonly my $COLD_WATER_METER_NUMBER => '111111';
Readonly my $HOT_WATER_METER_NUMBER  => '222222';

sub _create_user {
    my $user = Meter::Users->insert(
        {   username => $USERNAME,
            password => $PASSWORD,
            email    => $EMAIL,
        }
    );

    return $user;
}

sub _create_house {
    my $house = Meter::Houses->insert( { address => $ADDRESS } );

    return $house;
}

sub _create_appartment {
    my $appartment = Meter::Appartments->insert(
        {   user                    => _create_user(),
            house                   => _create_house(),
            appartment_number       => $APPARTMENT_NUMBER,
            first_name              => $FIRST_NAME,
            last_name               => $LAST_NAME,
            middle_name             => $MIDDLE_NAME,
            cold_water_meter_number => $COLD_WATER_METER_NUMBER,
            hot_water_meter_number  => $HOT_WATER_METER_NUMBER,
        }
    );

    return $appartment;
}

sub test_common_case {
    my $appartment = shift;

    my $metering_fields = {
        start_date              => '20110528',
        end_date                => '20110630',
        cold_water_start_amount => '33',
        cold_water_end_amount   => '39',
        hot_water_start_amount  => '20',
        hot_water_end_amount    => '22',
    };

    # create metering
    lives_ok {
        Meter::Meterings->insert(
            {   appartment => $appartment,
                %{$metering_fields},
            }
        );
    }
    'Create metering ' . dump_compact( $metering_fields, 'METERING' );

    # retrieve metering
    my $metering = Meter::Meterings->retrieve( %{$metering_fields} );
    ok( $metering,
        'Retrieve metering ' . dump_compact( $metering_fields, 'METERING' ) );

    # update metering
    Readonly my $NEW_COLD_WATER_START_AMOUNT => 30;
    my $updated_metering_fields = {
        %{$metering_fields},
        cold_water_start_amount => $NEW_COLD_WATER_START_AMOUNT,
    };

    lives_ok {
        $metering->cold_water_start_amount($NEW_COLD_WATER_START_AMOUNT);
        $metering->update();
    }
    'Update metering ' . dump_compact( $updated_metering_fields, 'METERING' );

    row_ok(
        table => 'meterings',
        where => [ %{$updated_metering_fields} ],
        label => 'Check database row for updated '
            . dump_compact( $updated_metering_fields, 'METERING' ),
    );

    # delete metering
    lives_ok {
        $metering->delete();
    }
    'Delete metering';

    not_row_ok(
        table => 'meterings',
        where => [ appartment_id => $appartment->appartment() ],
        label => 'Check NO database row for deleted metering',
    );

    return;
}

sub test_invalid_dates {
    my $appartment = shift;

    throws_ok {
        Meter::Meterings->insert(
            {   appartment              => $appartment,
                start_date              => '20110601',
                end_date                => '20110501',
                cold_water_start_amount => '33',
                cold_water_end_amount   => '39',
                hot_water_start_amount  => '20',
                hot_water_end_amount    => '22',
            }
        );
    }
    qr/\Qend_date fails 'end_date > start_date' constraint\E/xms,
        'Try to add metering with start_date > end_date';

    return;
}

sub test_invalid_amount {
    my $appartment = shift;

    ## no critic (RegularExpressions)
    throws_ok {
        Meter::Meterings->insert(
            {   appartment              => $appartment,
                start_date              => '20110501',
                end_date                => '20110601',
                cold_water_start_amount => '100',
                cold_water_end_amount   => '50',
                hot_water_start_amount  => '20',
                hot_water_end_amount    => '22',
            }
        );
    }
    qr/\Qcold_water_end_amount fails 'end_amount >= start_amount' constraint\E/xms,
        'Try to add metering with cold_water_start_amount > cold_water_end_amount';

    return;
}

sub run_tests {
    init_tmp_db();

    my $appartment = _create_appartment();

    test_common_case($appartment);
    test_invalid_dates($appartment);
    test_invalid_amount($appartment);

    return;
}

run_tests();
